package com.polaris.live.ui.live.widget

import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.forEach
import androidx.customview.widget.ViewDragHelper
import com.polaris.live.R.drawable
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.databinding.WidgetDragTranslationBinding
import com.polaris.live.im.sfs.bean.live.ext.UserBasicVo
import com.polaris.live.resp.back_resp.RecognizeModel

/**
 * 拖动缩小的翻译view
 * @author Created by 天晴 on 2024/5/10 14:11
 * @since 1.0.0
 **/
class DragTranslationView(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {

    val mBinding = WidgetDragTranslationBinding.inflate(LayoutInflater.from(context), this)

    private var mShowTranslation = true //显示
    private var mLeft = 0
    private var mTop = 0
    private var mTempTop = -1
    private var mTempLeft = -1
    private var mParentWidth: Int = 0   //当前控件宽
    private var mParentHeight: Int = 0  //当前控件高

    private var isInterceptToViewDragHelper = false //是否由ViewDragHelper接管拦截
    private var mDownTime = 0L //按下的时间
    private var mDownX = 0 //按下时的x
    private var mDownY = 0 //按下时的y
    private var mDownView: View? = null

    private var clickback: (() -> Unit)? = null
    private var mViewDragHelper: ViewDragHelper
    private var mBack = object : ViewDragHelper.Callback() {
        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            return mBinding.dragLl == child
        }

        override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
            mLeft = left
            val maxLeft = mParentWidth - child.width
            if (left > maxLeft) {
                mLeft = maxLeft
            }
            if (left < 0) {
                mLeft = 0
            }
            return mLeft
        }

        override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
            mTop = top
            val maxTop = mParentHeight - child.height
            if (top > maxTop) {
                mTop = maxTop
            }
            if (top < 0) {
                mTop = 0
            }
            return mTop
        }

        override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
            mTempTop = mTop
            mTempLeft = mLeft
            setLp(mLeft, mTop)
            requestLayout()
            invalidate()
            CacheUtil.saveTrAddr(mLeft, mTop)
        }
    }

    init {
        mViewDragHelper = ViewDragHelper.create(this, 1f, mBack)
        setLocalAddr()
    }

    fun setDragTranslationViewVisibility(mVisibility: Int) {
        visibility = mVisibility
        setLocalAddr()
    }

    /**
     * 是否展开
     */
    fun foldAndUnfold(expand: Boolean) {
        if (expand) {
            openTranslation()
        } else {
            closeTranslation()
        }

    }

    private fun setLocalAddr() {
        val adder = CacheUtil.getTrAddrFromKV()
        mLeft = adder[0]
        mTop = adder[1]
        calculateAddr()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mParentWidth = MeasureSpec.getSize(widthMeasureSpec)
        mParentHeight = MeasureSpec.getSize(heightMeasureSpec)
    }

    fun onTranslationText(otherUserBasic: UserBasicVo?, recognizeModel: RecognizeModel) {
        mBinding.vTransition.onTranslationText(
            otherUserBasic,
            recognizeModel
        )
    }

    fun initData(otherSex: Int?, avatar: String?, avatarFrame: String?, payer: Boolean) {
        mBinding.vTransition.initData(
            otherSex,
            avatar,
            avatarFrame,
            payer
        )
    }

    fun setClickCallback(back: () -> Unit) {
        clickback = back
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (visibility != VISIBLE) {
            return super.onInterceptTouchEvent(ev)
        }
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                mDownX = ev.x.toInt()
                mDownY = ev.y.toInt()
                isInterceptToViewDragHelper = isClickView(mDownX, mDownY)
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                isInterceptToViewDragHelper = false
            }
        }
        if (isInterceptToViewDragHelper) {
            return mViewDragHelper.shouldInterceptTouchEvent(ev)
        }
        return super.onInterceptTouchEvent(ev)
    }

    /**
     * 按下时是否点击到控件
     */
    private fun isClickView(x: Int, y: Int): Boolean {
        val view = mViewDragHelper.findTopChildUnder(x, y)
        return if (view == null) {
            false
        } else {
            mDownView = clickView(view, x, y)
            true
        }
    }

    private fun clickView(touchedView: View, x: Int, y: Int): View? {
        if (touchedView is ViewGroup) {
            touchedView.forEach { childView ->
                if (childView.visibility != View.GONE) {
                    val childRect = Rect().apply { childView.getHitRect(this) }
                    childRect.left = childRect.left + touchedView.left
                    childRect.top = childRect.top + touchedView.top
                    childRect.right = childRect.left + childView.width
                    childRect.bottom = childRect.top + childView.height
                    if (childRect.contains(x, y)) {
                        return when (childView) {
                            mBinding.trImg, mBinding.close, mBinding.vTransition -> childView
                            else -> null
                        }
                    }
                }
            }
        }
        return null
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (visibility != VISIBLE) {
            return super.onTouchEvent(event)
        }

        try {
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    if (isInterceptToViewDragHelper) {
                        mDownTime = System.currentTimeMillis()
                        mViewDragHelper.processTouchEvent(event)
                        return true
                    }
                }

                MotionEvent.ACTION_MOVE -> {
                    if (isInterceptToViewDragHelper) {
                        mViewDragHelper.processTouchEvent(event)
                        return true
                    }
                }

                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    if (isInterceptToViewDragHelper) {
                        //按下抬起时间小于150ms 判断为点击
                        if (System.currentTimeMillis() - mDownTime < 150) {
                            when (mDownView) {
                                mBinding.close -> {
                                    if (mShowTranslation) {
                                        closeTranslation()
                                    } else {
                                        openTranslation()
                                    }
                                }

                                mBinding.trImg -> {
                                    openTranslation()
                                }

                                mBinding.vTransition -> {
                                    clickback?.invoke()
                                }
                            }
                        } else {
                            mViewDragHelper.processTouchEvent(event)
                        }
                    }
                    mDownTime = 0L
                    isInterceptToViewDragHelper = false
                    mDownX = 0
                    mDownY = 0
                    mDownView = null
                }
            }
        } catch (_: Throwable) {
        }

        return super.onTouchEvent(event)
    }

    private fun closeTranslation() {
        mShowTranslation = false
        mBinding.apply {
            close.setImageResource(drawable.game_call_tr_open)
            dragLl.setBackgroundResource(drawable.r8_back_00adff)
            vTransition.visibility = GONE
            trImg.visibility = VISIBLE
            dragLl.requestLayout()
            dragLl.invalidate()
            if (mTempLeft != -1 && mTempTop != -1) {
                setLp(mTempLeft, mTempTop)
                mTempLeft = -1
                mTempTop = -1
            }
        }
    }

    /**
     * 展开同声传译界面
     */
    private fun openTranslation() {
        mShowTranslation = true
        //保存原始位置
        mTempTop = mTop
        mTempLeft = mLeft
        mBinding.apply {
            close.setImageResource(drawable.game_call_tr_close)
            dragLl.setBackgroundResource(0)
            vTransition.visibility = VISIBLE
            trImg.visibility = GONE
            calculateAddr()
        }
    }

    /**
     * 计算下能不能展开
     */
    private fun calculateAddr() {
        mBinding.dragLl.post {
            mBinding.dragLl.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
            val measuredWidth: Int = mBinding.dragLl.measuredWidth
            val measuredHeight: Int = mBinding.dragLl.measuredHeight

            val maxTop = mParentHeight - measuredHeight
            if (mTop > maxTop) {
                mTop = maxTop
            }
            if (mTop < 0) {
                mTop = 0
            }

            val maxLeft = mParentWidth - measuredWidth
            if (mLeft > maxLeft) {
                mLeft = maxLeft
            }
            if (mLeft < 0) {
                mLeft = 0
            }
            setLp(mLeft, mTop)
        }
    }

    fun setLp(left: Int, top: Int) {
        mLeft = left
        mTop = top
        val lp = mBinding.dragLl.layoutParams as MarginLayoutParams
        lp.topMargin = top
        lp.leftMargin = left
        mBinding.dragLl.layoutParams = lp

    }

    override fun computeScroll() {
        if (mViewDragHelper.continueSettling(true)) {
            postInvalidate()
        }
    }
}